----------------------------------------------------------------------------------
-- Company: BEEcube 
-- Engineer: Kiki
-- 
-- Create Date:    14:30:48 09/26/2012 
-- Design Name: 
-- Module Name:    cmd_gen - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity cmd_gen is
	generic( 
		ADDR_WIDTH         : integer := 21;          --Address Width
		DATA_WIDTH         : integer := 36;          --Data Width
		BURST_LEN          : integer := 4          --Burst Length
	);
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
			  sram_init_done : in STD_LOGIC;
			  sram_rst: out STD_LOGIC;
           wr_data : out  STD_LOGIC_VECTOR (BURST_LEN*DATA_WIDTH-1 downto 0);
		   wr_addr : out STD_LOGIC_VECTOR (ADDR_WIDTH -1 downto 0);
           wr_cmd : out  STD_LOGIC;
		   rd_addr : out STD_LOGIC_VECTOR (ADDR_WIDTH -1 downto 0);
           rd_cmd : out  STD_LOGIC);
end cmd_gen;

architecture Behavioral of cmd_gen is
type state_t is (start,sram_write,sram_read,idle,over);
signal state : state_t;
signal wr_data_buf	: std_logic_vector(BURST_LEN*DATA_WIDTH-1 downto 0);
signal wr_addr_buf : std_logic_vector(ADDR_WIDTH -1 downto 0);
signal rd_addr_buf : std_logic_vector(ADDR_WIDTH -1 downto 0);
signal wr_cmd_buf : std_logic;
signal rd_cmd_buf : std_logic;
signal count		: std_logic_vector(19 downto 0);

begin
--State sync and change
sync :process(rst,clk)
  begin
    if(rst = '1') then
	    state <= start;
		 wr_cmd_buf <= '0';
		 rd_cmd_buf <= '0';
		 sram_rst	<= '1';
		 count <= (others => '0');
    elsif(rising_edge(clk)) then

	case state is
		when start  =>
			wr_cmd_buf <= '0';
			rd_cmd_buf <= '0';
			sram_rst <= '1';
			if(count < x"fffff")then
				state <= start;
				count <= count + 1;
			else
				count <= (others => '0');
				state <= idle;
			end if;

		when sram_write =>
			sram_rst	<= '0';
			rd_cmd_buf <= '0';
			if(wr_addr_buf  < x"1ffffe")then
				wr_cmd_buf <= '1';
				state <= sram_write;
			else
				state <= sram_read;
			end if;

		when sram_read =>
			wr_cmd_buf <= '0';
			if(rd_addr_buf < x"1ffffe")then
				rd_cmd_buf <= '1';
				state <= sram_read;
			else
				state <= over;
			end if;

		when idle =>
			wr_cmd_buf <= '0';
			rd_cmd_buf <= '0';
			sram_rst	<= '0';
			if(sram_init_done = '0')then
				state <= idle;
			else
				state <= sram_write;
			end if;
		
		when over =>
			wr_cmd_buf <= '0';
			rd_cmd_buf <= '0';
			sram_rst	<= '0';			
			state <= over;

		when others =>
			state <= start;

	end case;
	end if;
end process sync;

addr_gen : process(rst,clk)
begin
	if(rst = '1') then
		wr_addr_buf <= (others => '0');
		rd_addr_buf <= (others => '0');
	elsif(rising_edge(clk))then
		if(wr_cmd_buf = '1')then
			wr_addr_buf <= wr_addr_buf + 1;
		else
			wr_addr_buf <= (others => '0');
		end if;
		
		if(rd_cmd_buf = '1')then
			rd_addr_buf <= rd_addr_buf + '1';
		else
			rd_addr_buf <= (others => '0');
		end if;
	end if;
end process addr_gen;


data_gen:for i in 1 to 8 generate
			wr_data_buf((I*DATA_WIDTH/2 -1) downto (I-1)*DATA_WIDTH/2 ) <= wr_addr_buf(DATA_WIDTH/2 -1 downto 0);
end generate data_gen;

wr_addr <= wr_addr_buf;
rd_addr <= rd_addr_buf;
wr_data <= wr_data_buf;
wr_cmd <= wr_cmd_buf;
rd_cmd <= rd_cmd_buf;
end Behavioral;

